#include "main.h"

#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#include "macro.h"
#include "luaglue.h"
#include "luaengine.h"
#include "misc.h"
#include "color.h"
#include "filesystem.h"
#include "logger.h"

#include "error.h"

int mainRunning;

int restoreDefaults();
void splitArgs(std::string cmd, std::vector<std::string> &args);
std::string promptForScript(std::vector<std::string> &args);

static BOOL WINAPI consoleControlCallback(DWORD dwCtrlType);

int main(int argc, char *argv[])
//int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance,
//	LPSTR lpszArgument, int nCmdShow)
{
	//int argc = __argc;
	//char **argv = __argv;
	mainRunning = true;
	SetConsoleCtrlHandler(consoleControlCallback, true);

	CLI_OPTIONS clio;
	handleCommandLineArguments(argc, argv, &clio);
    SetCurrentDirectory( getAppPath().c_str() );

    LuaEngine engine;
    if( !engine.init(&clio) ) {
        fprintf(stderr, "Error initializing Lua Engine\n");
        exit(1); }

    bool autoload = (clio.scriptSet);
    while(mainRunning)
    {
        restoreDefaults();

        if( !autoload) // Grab filename &args from user
		{
			clio.args.clear();
            std::string filename = promptForScript(clio.args);
			clio.scriptName = filename;
		}


        if( !engine.checkCommands(clio.scriptName, clio.args) )
        { // Not a command, but a script to run. So run it.
            if( !autoload )
            {
				// Fix script path
                std::string replacescript = SCRIPT_DIR;
                replacescript += clio.scriptName;
                clio.scriptName = replacescript;

                // Set execution path
                std::string exePath = getAppPath() + "/";
                exePath += getFilePath(clio.scriptName);
                Macro::instance()->setExecutionPath(exePath);
            }
            else
            {
                // Set execution path
                Macro::instance()->setExecutionPath(
					getFilePath(clio.scriptName));
            }

            engine.run(clio.scriptName, clio.args);
        }

        // Disable autoloading now that it has been used (if needed)
        autoload = false;

		if( mainRunning )
		{
			#ifdef	DISPLAY_DEBUG_MESSAGES
			Logger::instance()->add("DEBUG: Reinitializing engine.");
			#endif
			if( !engine.reinit(&clio) )
			{
				const char *err = "Failed to re-initialize Lua Engine.\n";
				fprintf(stderr, err);
				Logger::instance()->add(err);
			}
			#ifdef	DISPLAY_DEBUG_MESSAGES
			Logger::instance()->add("DEBUG: Reinit OK.");
			#endif
		}
    }
	#ifdef	DISPLAY_DEBUG_MESSAGES
	Logger::instance()->add("DEBUG: Engine cleanup.");
	#endif
    engine.cleanup();
    return 0;
}

int restoreDefaults()
{
    setColor(COLOR_LIGHTGRAY);
    return 0;
}


void splitArgs(std::string cmd, std::vector<std::string> &args)
{
    unsigned int startpos;
    startpos = cmd.find(' ');
    args.push_back( cmd.substr(0, startpos) );

    unsigned int lastpos = startpos;
    while(startpos != std::string::npos)
    {
        startpos = cmd.substr(lastpos+1).find(' ');
        std::string tmp = cmd.substr(lastpos+1, startpos);
        if( tmp != "" )
            args.push_back( tmp );
        lastpos += startpos +1;
    }
}

std::string promptForScript(std::vector<std::string> &args)
{
    std::string filename;

    while( kbhit() ) getch(); // Clear keyboard buffer

    printf("Please enter the script name to run.\n");
    printf("Type in \'exit\' (without quotes) to exit.\n");
    printf("Script> ");

    std::string fullcmd;
    std::cin.clear();
    getline(std::cin, fullcmd);
    std::cin.clear();

    splitArgs(fullcmd, args);

    filename = args[0];
	args.erase(args.begin()); // Don't return filename in args array
    return filename;
}

static BOOL WINAPI consoleControlCallback(DWORD dwCtrlType)
{
	switch(dwCtrlType)
	{
		case CTRL_C_EVENT:
		case CTRL_CLOSE_EVENT:
			mainRunning = false;
			return true;
		break;
	}

	return false;
}
